#ifndef GAMEENGINE_GEOMETRY_TOPOLOGY_HALFEDGE_MESH_H
#define GAMEENGINE_GEOMETRY_TOPOLOGY_HALFEDGE_MESH_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Topology/halfedge_accessor.h>

#include <list>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

template <class T> class HalfEdgeMeshFaceIterator;
template <class T> class HalfEdgeMeshEdgeIterator;
template <class T> class HalfEdgeMeshVertexIterator;

//=================================================================================

//! Class used to represent half-edge meshes
/*!
 *  A half-edge mesh stores linked lists of half-edges, half-edge vertices and half-edge faces
 *  and provides ways to iterate through them. A half-edge mesh can also check its validity,
 *  even though this operation is very slow and should be limited to debugging purposes.
 *
 *  This class can generally been seen as an API dedicated to manipulating safely half-edges.
 *
 @sa The HalfEdge class that represents half-edges, and the HalfEdgeMeshFaceIterator, the
     HalfEdgeMeshEdgeIterator and the HalfEdgeMeshVertexIterator that allow to iterate on
	 the half-edges, the half-edge vertices and the half-edge faces of the mesh.
 @todo Provide ways to manipulate the mesh, and\ to check the validity of the mesh
 */
template <class T>
class HalfEdgeMesh {
	//! The half-edge face iterator class is friend of the HalfEdgeMesh class to enable direct data access
	friend class HalfEdgeMeshFaceIterator<T>;
	//! The half-edge iterator class is friend of the HalfEdgeMesh class to enable direct data access
	friend class HalfEdgeMeshEdgeIterator<T>;
	//! The half-edge vertex iterator class is friend of the HalfEdgeMesh class to enable direct data access
	friend class HalfEdgeMeshVertexIterator<T>;

public:
	//! Typedef used to iterate on the faces of the mesh
	typedef HalfEdgeMeshFaceIterator<T> FaceIterator;
	//! Typedef used to iterate on the half-edges of the mesh
	typedef HalfEdgeMeshEdgeIterator<T> EdgeIterator;
	//! Typedef used to iterate on the vertices of the mesh
	typedef HalfEdgeMeshVertexIterator<T> VertexIterator;

	//! Typedef use to handle face counts
	typedef unsigned int FaceCount;
	//! Typedef use to handle half-edge counts
	typedef unsigned int EdgeCount;
	//! Typedef use to handle vertex counts
	typedef unsigned int VertexCount;

public:
	HalfEdgeMesh();
	virtual ~HalfEdgeMesh();

	HalfEdgeVertex<T>* find_vertex(const T& vertex) const;

	bool connect(const HalfEdgeFace<T>& face1, const HalfEdgeFace<T>& face2);
	bool disconnect(const HalfEdgeFace<T>& face1, const HalfEdgeFace<T>& face2);
	bool remove_face(const HalfEdgeFace<T>& face);

	FaceCount face_count() const;
	EdgeCount edge_count() const;
	VertexCount vertex_count() const;

	void clear();

private:
	HalfEdgeMesh(const HalfEdgeMesh& rhs);
	HalfEdgeMesh& operator=(const HalfEdgeMesh& rhs);

protected:
	HalfEdgeVertex<T>* add_or_find_vertex(const T& vertex);
	HalfEdgeVertex<T>* add_vertex(const T& vertex);

	bool remove_vertex(HalfEdgeVertex<T>* vertex);
	bool remove_edge(HalfEdge<T>* edge);
	bool remove_face(HalfEdgeFace<T>* face);

protected:
	//! List of faces associated to the mesh
	std::list< HalfEdgeFace<T>* > faces_;
	//! List of edges associated to the mesh
	std::list< HalfEdge<T>* > edges_;
	//! List of vertices associated to the mesh
	std::list< HalfEdgeVertex<T>* > vertices_;
};

//=====================================================================

//! Class used to iterate over the faces of half-edge meshes
/*!
 *  This iterator allows to visit once only all the faces of the half-edge
 *  mesh (as opposed to mesh propagation using adjacency informations, where
 *  a face can be visited several times - or never, if it is not somehow
 *  connected to the starting face).
 *
 *  An example of such an iteration would be:
 *  @code
 *  HalfEdgeMesh<T> mesh = ...;
 *  for ( HalfEdgeMeshFaceIterator<T> it(mesh); it.more(); it.next() ) {
 *		// Get current face
 *		HalfEdgeFaceAccessor<T> current_face = cur();
 *  
 *		// do stuff...
 *  }
 *  @endcode
 *
 *  Strictly speaking, this class uses STL iterators to iterate on the mesh
 *  faces, but provides a pointer-safe access using HalfEdgeMeshFaceAccessor
 *  objects.
 *
 @sa The HalfEdgeMesh class to manipulate meshes made of half-edges.
 */
template <class T>
class HalfEdgeMeshFaceIterator {

public:
	HalfEdgeMeshFaceIterator(const HalfEdgeMesh<T>& mesh);
	virtual ~HalfEdgeMeshFaceIterator();

	bool more() const;
	void next();
	HalfEdgeFaceAccessor<T> cur() const;

private:
	HalfEdgeMeshFaceIterator(const HalfEdgeMeshFaceIterator& rhs);
	HalfEdgeMeshFaceIterator& operator=(const HalfEdgeMeshFaceIterator& rhs);

protected:
	//! Iterator on the faces
	std::list< HalfEdgeFace* >::const_iterator it_;

	//! The half-edge mesh on which to iterate
	const HalfEdgeMesh<T>& mesh_;
};

//=====================================================================

//! Class used to iterate over the edges of half-edge meshes
/*!
 *  This iterator allows to visit once only all the edges of the half-edge
 *  mesh (as opposed to mesh propagation using adjacency informations, where
 *  an edge can be visited several times - or never, if it is not somehow
 *  connected to the starting edge).
 *
 *  An example of such an iteration would be:
 *  @code
 *  HalfEdgeMesh<T> mesh = ...;
 *  for ( HalfEdgeMeshEdgeIterator<T> it(mesh); it.more(); it.next() ) {
 *		// Get current half-edge
 *		HalfEdgeAccessor<T> current_edge = cur();
 *  
 *		// do stuff...
 *  }
 *  @endcode
 *
 *  Strictly speaking, this class uses STL iterators to iterate on the mesh
 *  half-edges, but provides a pointer-safe access using HalfEdgeMeshAccessor
 *  objects.
 *
 @sa The HalfEdgeMesh class to manipulate meshes made of half-edges.
 */
template <class T>
class HalfEdgeMeshEdgeIterator {

public:
	HalfEdgeMeshEdgeIterator(const HalfEdgeMesh<T>& mesh);
	virtual ~HalfEdgeMeshEdgeIterator();

	bool more() const;
	void next();
	HalfEdgeAccessor<T> cur() const;

private:
	HalfEdgeMeshEdgeIterator(const HalfEdgeMeshEdgeIterator& rhs);
	HalfEdgeMeshEdgeIterator& operator=(const HalfEdgeMeshEdgeIterator& rhs);

protected:
	//! Iterator on the faces
	std::list< HalfEdge* >::const_iterator it_;

	//! The half-edge mesh on which to iterate
	const HalfEdgeMesh<T>& mesh_;
};

//=====================================================================

//! Class used to iterate over the vertices of half-edge meshes
/*!
 *  This iterator allows to visit once only all the vertices of the half-edge
 *  mesh (as opposed to mesh propagation using adjacency informations, where
 *  a vertex can be visited several times - or never, if it is not somehow
 *  connected to the starting vertex).
 *
 *  An example of such an iteration would be:
 *  @code
 *  HalfEdgeMesh<T> mesh = ...;
 *  for ( HalfEdgeMeshVertexIterator<T> it(mesh); it.more(); it.next() ) {
 *		// Get current face
 *		HalfEdgeVertexAccessor<T> current_vertex = cur();
 *  
 *		// do stuff...
 *  }
 *  @endcode
 *
 *  Strictly speaking, this class uses STL iterators to iterate on the mesh
 *  vertices, but provides a pointer-safe access using HalfEdgeVertexAccessor
 *  objects.
 *
 @sa The HalfEdgeMesh class to manipulate meshes made of half-edges.
 */
template <class T>
class HalfEdgeMeshVertexIterator {

public:
	HalfEdgeMeshVertexIterator(const HalfEdgeMesh<T>& mesh);
	virtual ~HalfEdgeMeshVertexIterator();

	bool more() const;
	void next();
	HalfEdgeVertexAccessor<T> cur() const;

private:
	HalfEdgeMeshVertexIterator(const HalfEdgeMeshVertexIterator& rhs);
	HalfEdgeMeshVertexIterator& operator=(const HalfEdgeMeshVertexIterator& rhs);

protected:
	//! Iterator on the faces
	std::list< HalfEdgeVertex* >::const_iterator it_;

	//! The half-edge mesh on which to iterate
	const HalfEdgeMesh<T>& mesh_;
};

//=================================================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Topology/halfedge_mesh.hpp>

#endif
